﻿using Microsoft.ServiceModel.Web;
using System.Web.Security;
using Ezio.Model;
using System.ServiceModel.Channels;
using System.Net;
using System.Linq;
using System;

namespace Ezio.Interceptor
{
    public class BasicAuthenticationInterceptor : RequestInterceptor
    {
        string URL;
        Users User;
        DataProvider DataProvider = new DataProvider();

        MembershipProvider provider;
        string realm;
        


        public BasicAuthenticationInterceptor(MembershipProvider provider, string realm)
            : base(false)
        {
            this.provider = provider;
            this.realm = realm;
        }

        protected string Realm
        {
            get { return realm; }
        }

        protected MembershipProvider Provider
        {
            get { return provider; }
        }

        public override void ProcessRequest(ref RequestContext requestContext)
        {
            string Token = ExtractCredentials(requestContext.RequestMessage);

            if (IsValid(Token))
            {
                URL = requestContext.RequestMessage.Headers.To.LocalPath;
                string HttpMethod = ExtractHttpMethod(requestContext.RequestMessage);
                string ServiceName = ExtractServiceName();
                string URI = ExtractURI();
                URI = URI == string.Empty ? null : URI;

                if (User.Privileges.Any(t => t.HttpMethod == HttpMethod && t.Service == ServiceName && t.URI == URI))
                {
                    UpdateSession(Token);
                    return;
                }
            }

            requestContext = null;
        }

        private bool IsValid(string Token)
        {
            bool IsValid = DataProvider.Sessions.Any(t => t.Token == Token && t.ExpiryDate >= DateTime.Now);
            if (IsValid)
            {
                User = DataProvider.Sessions.Single(t => t.Token == Token).Users;
            }

            return IsValid;
        }

        private string ExtractCredentials(Message requestMessage)
        {
            HttpRequestMessageProperty request = (HttpRequestMessageProperty)requestMessage.Properties[HttpRequestMessageProperty.Name];
            return request.Headers[HttpRequestHeader.Authorization];
        }

        private string ExtractHttpMethod(Message requestMessage)
        {
            HttpRequestMessageProperty HttpMethod = (HttpRequestMessageProperty)requestMessage.Properties[HttpRequestMessageProperty.Name];
            return HttpMethod.Method;
        }

        private string ExtractServiceName()
        {
            string ServiceName = URL.Substring(6);
            return ServiceName.Substring(0, ServiceName.IndexOf("/"));
        }

        private string ExtractURI()
        {
            string ServiceName = ExtractServiceName();
            string URI = URL.Substring(URL.IndexOf(ServiceName) + ServiceName.Length + 1);
            return URI;
        }

        private void UpdateSession(string Token)
        {
            Sessions Session = DataProvider.Sessions.Single(t => t.Token == Token);
            Session.ExpiryDate = DateTime.Now.AddMinutes(10);

            DataProvider.TrySaveChanges();
        }
    }
}